//生产者消费者模式

# include<iostream>
using namespace std;
# include<thread>
# include<vector>
# include<mutex>
# include<condition_variable>
# include<queue>
#include <windows.h>
//生产者数量
# define PRODUCT_SIZE 10
//消费者数量
# define CUSTOMER_SIZE 1
//最大产品数量
#define MAX_SIZE 10
//互斥锁
mutex mut;
//条件变量
condition_variable con;
//队列，模拟缓冲区
queue<int> que;
void Producter()
{

    while (true)
    {
        Sleep(10);
        std::unique_lock <std::mutex> lck(mut);
        while (que.size() > MAX_SIZE)
        {

            con.wait(lck);
        }
        int data = rand();
        que.push(data);//在 queue 的尾部添加一个元素的副本
        cout << this_thread::get_id() << "生产了产品：" << data << endl;
        con.notify_all();

    }
}
void Customer()
{
    while (true)
    {
        //这句代码会获取到全局的互斥锁mut，并且自动进行加锁操作。
        //还有需要注意的是，lck作为局部变量，当一次循环介绍后，
        //会自动调用自己的析构函数，来对锁进行解锁操作。
        std::unique_lock <std::mutex> lck(mut);
        while (que.empty())
        {
            con.wait(lck); //这句代码，当条件成立的时候，
            //条件变量的成员函数wait首先会对锁进行解锁操作，
            //然后会将线程挂起（suppend），当条件变量被noty_* 系列函数唤醒的时候，
            //会将锁再次进行加锁。
        }
        cout << this_thread::get_id() << "消费了产品：" << que.front() << endl;
        que.pop(); //删除 queue 中的第一个元素
        con.notify_all();
    }
}
int main()
{
    vector<thread> threadPoll;
    //创建生产者和消费者
    for (int i = 0; i < PRODUCT_SIZE; ++i)
    {
        threadPoll.push_back(thread(Producter));
    }
    for (int i = 0; i < PRODUCT_SIZE + CUSTOMER_SIZE; ++i)
    {
        threadPoll.push_back(thread(Customer));
    }


    for (int i = 0; i < PRODUCT_SIZE + CUSTOMER_SIZE; ++i)
    {
        threadPoll[i].join();
    }

    return 0;
}